package com.lowca.news.service.impl;

import java.util.Collection;
import java.util.Set;

import javax.annotation.Resource;

import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;

import com.lowca.news.dao.RoleDao;
import com.lowca.news.entity.Role;
import com.lowca.news.entity.User;
import com.lowca.news.service.RoleService;

@Service("roleService")
public class RoleServiceImpl implements RoleService {

	@Resource
	private RoleDao roleDao;

	@Override
	public void createRoles(Set<Role> roles) {
		for (Role role : roles) {
			roleDao.save(role);
		}
	}

	@Override
	public boolean existRoleByName(String name) {
		return roleDao.existByProperty("name", name);
	}

	private UserDetails getUserDetails() {
		Object principal = SecurityContextHolder.getContext()
				.getAuthentication().getPrincipal();
		UserDetails userDetails = null;
		if (principal instanceof UserDetails) {
			userDetails = (UserDetails) principal;
		}
		return userDetails;
	}

	private boolean isRolePresent(Collection<GrantedAuthority> authorities,
			String role) {
		boolean isRolePresent = false;
		for (GrantedAuthority grantedAuthority : authorities) {
			isRolePresent = grantedAuthority.getAuthority().equals(role);
			if (isRolePresent)
				break;
		}
		return isRolePresent;
	}

	@Override
	public boolean hasAnyRoles(String... roleNames) {
		Assert.notNull(roleNames, "roleNames is required");
		UserDetails userDetails = getUserDetails();
		boolean hasRole = false;
		if (userDetails != null) {
			Collection<GrantedAuthority> authorities = userDetails
					.getAuthorities();
			for (String roleName : roleNames) {
				if (isRolePresent(authorities, roleName)) {
					hasRole = true;
					break;
				}
			}
		}
		return hasRole;
	}

	@Override
	public void addRoleToUser(User user, String roleName) {
		Role role = roleDao.findByName(roleName);
		role.getUsers().add(user);
		user.getRoles().add(role);
		roleDao.update(role);
	}

	@Override
	public boolean hasAnyRoles(User user, String... roleNames) {
		Assert.notNull(roleNames, "roleNames is required");
		Set<Role> roles = user.getRoles();
		for (String roleName : roleNames) {
			for (Role role : roles) {
				if (role.getName().equals(roleName)) {
					return true;
				}
			}
		}
		return false;
	}

	@Override
	public void removeRoleFromUser(User user, String roleName) {
		Assert.notNull(roleName, "roleName is required");
		Set<Role> roles = user.getRoles();
		Role roleForRemove = null;
		for (Role role : roles) {
			if (role.getName().equals(roleName)) {
				roleForRemove = role;
				break;
			}
		}
		if (roleForRemove != null) {
			roleDao.delete(roleForRemove);
		}
	}

}
